package com.skillworld.webapp.model.enrollment;

import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;

import org.springframework.stereotype.Repository;

import com.skillworld.webapp.model.course.Course;
import com.skillworld.webapp.model.department.Department;
import com.skillworld.webapp.model.tutorial.MarkedTutorial.Mark;
import com.skillworld.webapp.model.user.User;
import com.skillworld.webapp.model.util.dao.GenericDaoHibernate;

import es.udc.pojo.modelutil.exceptions.InstanceNotFoundException;


@Repository("enrollmentDao")
public class EnrollmentDaoHibernate 
        extends GenericDaoHibernate<Enrollment,Long>
        implements EnrollmentDao
{

    private Criteria buildSearch(List<String> keywords, 
                                    Long user, Long dept,
                                    Locale locale, Boolean finished)
    {
        Criteria q = getSession().createCriteria(Enrollment.class);

        q.createAlias("course", "c");

        for (String k : keywords)
        {
            Criterion inName = Restrictions.ilike("c.name", k, MatchMode.ANYWHERE);
            Criterion inDescr = Restrictions.ilike("c.description", k, MatchMode.ANYWHERE);
            q.add(Restrictions.or(inName, inDescr));
        }
        
        if (user != null)
        { q.add(Restrictions.eq("student.userId", user)); }

        if (dept != null)
        { q.add(Restrictions.eq("c.department.departmentId", dept)); }

        if (locale != null)
        { q.add(Restrictions.le("c.locale", locale)); }

        if (finished != null)
        {
            if (finished)
            { q.add(Restrictions.isNotNull("finishDate")); }
            else
            { q.add(Restrictions.isNull("finishDate")); }
        }

        return q;
    }

    @SuppressWarnings("unchecked")
    public List<Enrollment> search(List<String> keywords, 
                                        Long user, Long dept,
                                        Locale locale,
                                        Boolean finished, int startIndex, int count)
    {
        return(List<Enrollment>)
                    buildSearch(keywords, user, dept, locale, finished)
                        .addOrder(Order.desc("enrollmentDate"))
                        .setFirstResult(startIndex)
                        .setMaxResults(count)
                        .list();
    }

    public long numberOfEnrollments(List<String> keywords, 
                                    Long user, Long dept,
                                    Locale locale, Boolean finished)
    {
        return(Long) buildSearch(keywords, user, dept, locale, finished)
                        .setProjection(Projections.rowCount())
                        .uniqueResult();
    }
    
    public Enrollment find(long courseId, long userId) 
            throws InstanceNotFoundException
    {
        Enrollment enrollment =(Enrollment)
                getSession().createQuery(
                        "SELECT e " +
                        "  FROM Enrollment e " +
                        " WHERE e.course.courseId = :courseId " +
                        "   AND e.student.userId = :userId")
                    .setParameter("courseId", courseId)
                    .setParameter("userId", userId)
                    .uniqueResult();
        
        if(enrollment == null)
        { throw new InstanceNotFoundException(courseId, Enrollment.class.getName()); }
        
        return enrollment;
    }
    
	public boolean exists(long courseId, long userId)
	{
		return getSession().createQuery(
		                "SELECT e.enrollmentId " +
                	    "  FROM Enrollment e " +
                	    " WHERE e.course.courseId = :courseId " +
                	    "   AND e.student.userId = :userId")
                	.setParameter("courseId", courseId)
                	.setParameter("userId", userId)
					.uniqueResult() != null;
	}
	
	public List<Enrollment> findCourses(Long idUser){
		@SuppressWarnings("unchecked")
        List<Enrollment> list = (List<Enrollment>) getSession().createQuery(
                " from Enrollment s "
                +" WHERE s.student.userId = :idS")
                .setFirstResult(0)
            	.setParameter("idS", idUser)
				.list();
		
		System.out.println("\n\n\n\n\n" + list.size() + "\n\n\n\n\n");
		
		return list;
    }
	
	public List<Course> filtra(List<Enrollment> lista){
		List<Course> filtred = null; 
		Course course = null; 
		
		if(lista == null) return null;
		
		else{
			filtred = new ArrayList<Course>();
			for(Enrollment sc : lista)
			{	course = sc.getCourse();
				filtred.add(course);}
		}
		return filtred;
	}

	public Enrollment findByUserCourse(Long courseId, Long idStudent){
		@SuppressWarnings("unchecked")
        Enrollment  studentCourse = (Enrollment) getSession().createQuery(
                "SELECT sc FROM Enrollment sc " +
                "where sc.idUser = :idU and sc.idCourse = idC")
                .setFirstResult(0)
                .setParameter("idU", idStudent)
                .setParameter("idC", courseId);
		return studentCourse; 
	}
}
